package chapter2.eg5;

import io.netty.util.CharsetUtil;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;

public class ConnectCompletionHandler implements CompletionHandler<Void, AsynchronousSocketChannel> {

  private CountDownLatch latch;

  public ConnectCompletionHandler(CountDownLatch latch) {
    this.latch = latch;
  }

  @Override
  public void completed(Void result, AsynchronousSocketChannel channel) {
    ByteBuffer buffer = ByteBuffer.wrap("Hello, I'm client. ".getBytes());
    channel.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
      @Override
      public void completed(Integer result, ByteBuffer buffer) {
        if (buffer.hasRemaining()) {
          channel.write(buffer, buffer, this);
        } else {
          ByteBuffer readBuffer = ByteBuffer.allocate(1024);
          channel.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
              attachment.flip();
              byte[] bytes = new byte[attachment.remaining()];
              readBuffer.get(bytes);
              try {
                System.out.println("Client receives message: ");
                System.out.println(new String(bytes, StandardCharsets.UTF_8));
                latch.countDown();
              } catch (Exception e) {
                e.printStackTrace();
              }
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
              try {
                channel.close();
                latch.countDown();
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          });
        }
      }

      @Override
      public void failed(Throwable exc, ByteBuffer attachment) {
        try {
          channel.close();
          latch.countDown();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    });
  }

  @Override
  public void failed(Throwable exc, AsynchronousSocketChannel attachment) {

  }
}
